#include "Transformation.h"
#include <GL\glui.h>
#include <map>

map<string, void (*)(TiXmlElement *, Transformation *)> tag_parser;

void parseTranslate(TiXmlElement *elem, Transformation *t) {
	float x, y, z;
	
	elem->QueryFloatAttribute("x", &x);
	elem->QueryFloatAttribute("y", &y);
	elem->QueryFloatAttribute("z", &z);

	glTranslatef(x, y, z);
}

void parseRotate(TiXmlElement *elem, Transformation *t) {
	float angle, x = 0.0, y = 0.0, z = 0.0;
	char cc = elem->Attribute("axis")[0];
	
	elem->QueryFloatAttribute("angle", &angle);
	
	x = (cc == 'x' ? 1.0 : 0.0);
	y = (cc == 'y' ? 1.0 : 0.0);
	z = (cc == 'z' ? 1.0 : 0.0);
	
	glRotatef(angle, x, y, z);
}

void parseScale(TiXmlElement *elem, Transformation *t) {
	float x, y, z;
	
	elem->QueryFloatAttribute("x", &x);
	elem->QueryFloatAttribute("y", &y);
	elem->QueryFloatAttribute("z", &z);
	
	glScalef(x, y, z);
}

void initTagParsers() {
	if( tag_parser.empty() ) {
		tag_parser["translate"] = parseTranslate;
		tag_parser["rotate"] = parseRotate;
		tag_parser["scale"] = parseScale;
	}
}

void Transformation::parseTransformations(TiXmlElement *elem) {
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	for( ; elem != NULL; elem = elem->NextSiblingElement() ) {
		tag_parser[elem->Value()](elem, this);
	}
	
	glGetFloatv(GL_MODELVIEW_MATRIX, this->matrix);
	glPopMatrix();
}

void Transformation::multMatrix(float m[]) {
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glMultMatrixf( m );
	glMultMatrixf( this->matrix );
	glGetFloatv(GL_MODELVIEW_MATRIX, this->matrix);
	glPopMatrix();
}

Transformation::Transformation(TiXmlElement *elem) {
	initTagParsers();

	this->id = elem->Attribute("id");
	
	this->parseTransformations(elem->FirstChildElement());
}

Transformation::Transformation() : id(generateID()) {
	initTagParsers();
	
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glGetFloatv(GL_MODELVIEW_MATRIX, this->matrix);
	glPopMatrix();

}